package afcp.alumni.dao.base;

//import java.util.LinkedList;
//import java.util.List;
//
//import javax.persistence.EntityManager;
//import javax.persistence.EntityManagerFactory;
//import javax.persistence.EntityTransaction;
//import javax.persistence.Persistence;
//import javax.persistence.TypedQuery;
//
//import org.apache.commons.logging.Log;
//import org.apache.commons.logging.LogFactory;
//
//import afcp.alumni.model.base.DatastoreEntity;
//
//import com.google.appengine.api.datastore.Key;
//import com.google.appengine.api.datastore.KeyFactory;
//
//public abstract class DaoDatastoreJPA<T extends DatastoreEntity> extends DaoDatastoreCommon<T> {
//	
//	private static final Log logger = LogFactory.getLog(DaoDatastoreJPA.class);
//	
//	protected static final EntityManagerFactory emfInstance = Persistence
//			.createEntityManagerFactory("transactions-optional");
//	protected static final EntityManager entityManager = emfInstance
//			.createEntityManager();
//	
////	protected DaoDatastoreJPA() {
////	}
//
//	@Deprecated
//	protected void persist(T entity) {
//		if (entity != null) {
//			EntityTransaction tx = null;
////			EntityManager entityManager = emfInstance.createEntityManager();
//			try {
//				tx = entityManager.getTransaction();
//				tx.begin();
//				entityManager.persist(entity);
//				entityManager.flush();
//				tx.commit();
//			} catch (Exception e) {
//				logger.error("Persist failed. Rollback...", e);
//				if (tx != null && tx.isActive())
//					tx.rollback();
//			} finally {
////				entityManager.close();
//			}
//		}
//	}
//
//	public List<T> findAll() {
//		TypedQuery<T> query = entityManager.createQuery(
//				"SELECT e FROM " + this.className + " e", this.getClassObject());
//		List<T> entitiesFound = query.getResultList();
//		// TODO temp : to update members in database
////		for (T entity : entitiesFound) {
//////			if (entity instanceof Member) {
//////				Member member = (Member) entity;
////				entity.setId(entity.getKey().getName());
////				EntityTransaction tx = entityManager.getTransaction();
////				tx.begin();
////				entityManager.flush();
////				tx.commit();
//////			}
////		}
//		// end temp
//		return entitiesFound;
//	}
//
//
//	/**
//	 * <p>
//	 * Find and return the entity with the given id (the number form).
//	 * </p>
//	 * <p>
//	 * Warning: The returned entity is detached. For instance, it can't be used
//	 * to remove it from the datastore.
//	 * </p>
//	 * 
//	 * @deprecated
//	 * @param id
//	 * @return
//	 */
//	public T find(long id) {
//		logger.info("Searching for entity " + this.className + " with id: " + id);
//		Key key = KeyFactory.createKey(getAncestorKey(), this.className, id);
////		EntityManager entityManager = emfInstance.createEntityManager();
//		T entity = entityManager.find(this.getClassObject(), key);
////		entityManager.close();
//		return entity;
//	}
//
//	public T find(String id) {
//		logger.info("Searching for entity " + this.className + " with id: " + id);
//		Key key = KeyFactory.createKey(getAncestorKey(), this.className, id);
////		EntityManager entityManager = emfInstance.createEntityManager();
//		T entity = entityManager.find(this.getClassObject(), key);
////		entityManager.close();
//		return entity;
//	}
//	
//	public List<T> find(List<String> ids) {
//		logger.info("Searching for entity " + this.className + " with ids: " + ids);
////		EntityManager entityManager = emfInstance.createEntityManager();
//		List<T> entities = new LinkedList<>();
//		for (String id : ids) {
//			Key key = KeyFactory.createKey(getAncestorKey(), this.className, id);
//			T entity = entityManager.find(this.getClassObject(), key);
//			entities.add(entity);
//		}
////		entityManager.close();
//		return entities;
//	}
//	
//	public boolean exists(T entity) {
//		logger.info("Checking if entity " + this.className + " with id: " + entity.getId() + " exists.");
//		setKey(entity);
////		String id = entity.getId();
////		T oldEntity = entityManager.find(this.getClassObject(),
////				KeyFactory.createKey(getAncestorKey(), this.className, id));
//		T oldEntity = entityManager.find(this.getClassObject(), entity.getKey());
//		boolean exists = oldEntity != null;
//		if (exists) {
//			logger.info("entity " + this.className + " with id: " + oldEntity.getId() + " and key: " + oldEntity.getKey() + " already exists.");
//		}
//		return exists;
//	}
//
//	public boolean addOrUpdate(T entity) {
//		if (entity != null) {
//			setKey(entity);
////			EntityTransaction tx = null;
////			EntityManager entityManager = emfInstance.createEntityManager();
//			
////			String id = entity.getId();
////			try {
////				T oldEntity = entityManager.find(this.getClassObject(),
////						KeyFactory.createKey(this.className, id));
//				if (exists(entity)) {
//					logger.info("An entity " + this.className + " already exists in database with this id: " + entity.getId());
//					
////					// debug code because a member was found sometimes even after it was deleted. The application must be restarted to unlock the locked Id...
////					if (oldEntity instanceof Member) {
////						logger.error("Member");
////						Member member = (Member)oldEntity;
////						logger.error("Id:"+member.getId() + " / firstName:" + member.getFirstName() + " / lastName:" + member.getLastName() + " / password:" + member.getPassword());
////					}
//					
//				} else {
//					logger.info("Add entity " + this.className + " with id: " + entity.getId());
////					tx = entityManager.getTransaction();
////					tx.begin();
//					entityManager.persist(entity);
////					entityManager.flush();
////					tx.commit();
//					return true;
//				}
////			} catch (Exception e) {
////				logger.error("Persist failed. Rollback...", e);
////				if (tx != null && tx.isActive())
////					tx.rollback();
////			}
//		} else {
//			logger.error("Can't add null entity " + this.className + " to database.");
//		}
//		return false;
//	}
//	
//	public boolean addOrUpdate(List<T> entities) {
////		EntityTransaction tx = null;
////		try {
////			tx = entityManager.getTransaction();
////			tx.begin();
//			for (T entity : entities) {
////				if (exists(entity)) {
////					logger.info("An entity already exists in database with this id: " + entity.getId());
////				} else {
////					entityManager.persist(entity);
////				}
//				this.addOrUpdate(entity);
//			}
////			entityManager.flush();
////			tx.commit();
//			return true;
////		} catch (Exception e) {
////			logger.error("Persist failed. Rollback...", e);
////			if (tx != null && tx.isActive())
////				tx.rollback();
////		}
////		return false;
//	}
//
////	public T remove(T entity) {
////		if (entity != null) {
////			EntityTransaction tx = null;
////			EntityManager em = emfInstance.createEntityManager();
////			try {
////				tx = em.getTransaction();
////				tx.begin();
////				em.remove(entity);
////				tx.commit();
////			} catch (Exception e) {
////				logger.error("Deletion failed. Rollback...", e);
////				if(tx != null && tx.isActive()) tx.rollback();
////			} finally {
////				em.close();
////			}
////		}
////		return entity;
////	}
//
//	public T removeFromKeyString(String id) {
//		logger.info("Remove entity " + this.className + " with id: " + id);
//		// return this.remove(this.find(id));
//		T entity = null;
////		EntityTransaction tx = null;
////		EntityManager entityManager = emfInstance.createEntityManager();
////		try {
////			tx = entityManager.getTransaction();
////			tx.begin();
//		
////			entity = entityManager.find(this.getClassObject(),
////					KeyFactory.createKey(getAncestorKey(), this.className, id));
////			entityManager.remove(entity);
//			
//
//			try {
//				TypedQuery<T> query = entityManager.createQuery(
//						"DELETE FROM " + this.className + " e WHERE e.id = :id", this.getClassObject());
//				query.setParameter("id", id);
//				query.executeUpdate();
//			} catch (Exception e) {
//				logger.error("An error occured while deleting the entity " + this.className + " with id: " + id, e);
//				return null;
//			}
//			
////			em.persist(entity);
////			entityManager.flush();
////			tx.commit();
////		} catch (Exception e) {
////			logger.error("Deletion failed. Rollback...", e);
////			if (tx != null && tx.isActive())
////				tx.rollback();
////		}
//		return entity;
//	}
//	
//	public boolean remove(List<T> entities) {
////		if (logger.isInfoEnabled()) {
////			StringBuilder builder = new StringBuilder();
////			builder.append("Liste des entités supprimées : ");
////			for (T entity : entities) {
////				builder.append(entity.getId()).append(", ");
////			}
////			logger.info(builder);
////		}
//		
//		// TODO may be optimized with a single query removing all entities in one go.
////		EntityTransaction tx = null;
////		try {
////			tx = entityManager.getTransaction();
////			tx.begin();
////			for (String id : ids) {
//			for (T entity : entities) {
////				entity = entityManager.find(this.getClassObject(), 
////						KeyFactory.createKey(this.className, entity.getId()));
////				// The point: the remove() method is called once for each entity.
////				entityManager.remove(entity);
//				if (this.removeFromKeyString(KeyFactory.keyToString(entity.getKey())) == null) {
//					return false;
//				}
//			}
////			entityManager.flush();
//			return true;
////			tx.commit();
////			entityManager.flush();
////		} catch (Exception e) {
////			logger.error("Deletion failed. Rollback...", e);
////			if (tx != null && tx.isActive())
////				tx.rollback();
////		}
////		return false;
//		
//		// Example of optimization (to adapt):
////		@Override
////		public void deleteAllEmployees() {
////			transactionTemplate.execute(new TransactionCallback(){
////				@Override
////				public Object doInTransaction(TransactionStatus status) {
////					Query q = em.createQuery ("DELETE FROM Employee");
////					int deleted = q.executeUpdate ();
////					return null;
////				}});
////		}
//	}
//	
//	public boolean removeAll() {
//		logger.info("will remove entities " + this.className);
////		try {
////			TypedQuery<T> q = entityManager.createQuery("DELETE FROM " + this.className + " m", this.getClassObject());
////			q.executeUpdate();
////		} catch (Exception e) {
////			logger.error("An error occured while trying to delete all entities of class " + this.className, e);
////		}
//		List<T> entities = findAll();
//		try {
//			for (T entity : entities) {
//				T entityInDatastore = entityManager.find(this.getClassObject(), 
//						KeyFactory.createKey(this.getAncestorKey(), this.className, entity.getId()));
//				// The point: the remove() method is called once for each entity.
//				if (entityInDatastore != null) {
//					logger.info("remove entity " + this.className + " with id: " + entityInDatastore.getId());
//					entityManager.remove(entityInDatastore);
//				} else {
//					logger.info("entity " + this.className + " with id: " + entity.getId() + " not found in datastore.");
//				}
//			}
//		} catch (Exception e) {
//			logger.error("An error occurred while trying to delete all entities " + this.className + ".", e);
//			return false;
//		}
//		
//		return true;
//	}
//
//	public boolean update(T entity) {
//		logger.info("Update entity " + this.className + " with id: " + entity.getId());
//		//TODO code à tester, c'est pas sûr que ça fonctionne, en particulier avec les variables
//		// qui n'ont pas été définies pendant cette session.
////		emfInstance.createEntityManager().flush();
//		entityManager.flush();
//		return true;
//	}
//
//}
